﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TanmiaGrp.Basis;
using TanmiaGrp.Basis.Core;
using TanmiaGrp.Basis.Specification;
using TanmiaGrp.GeneralLedger.Core;
using TanmiaGrp.GeneralLedger.IRepository;
using TanmiaGrp.GeneralLedger.IRepository.Basis;

namespace TanmiaGrp.GeneralLedger.Domain
{
    public class BaseDomain<TBusinessObject, TBusinessDomain>
        where TBusinessObject : BusinessObject, new()
        where TBusinessDomain : BaseDomain<TBusinessObject, TBusinessDomain>, new()
    {
        protected readonly int PageSize = ConfigManager.Obj.PageSize;

        protected static IGenericQueryRepository QueryRepository { get; set; }
        protected static IGenericRepository Repository { get; set; }

        public static TBusinessDomain Obj { get; set; }

        static BaseDomain()
        {
            Obj = new TBusinessDomain();
        }

        public BaseDomain()
        {
            InitializeRepositories();
        }

        protected virtual void InitializeRepositories()
        {
            QueryRepository = RepositoryFactory.CreateQueryRepository();
            Repository = RepositoryFactory.CreateRepository();
        }

        public virtual TBusinessObject Add(TBusinessObject entity)
        {
            if (entity == null)
                throw new DomainException("يجب أن لايكون الكائن فارغاً");

            // the return value represent the persisted entity
            // if the creation done successfully.
            return Repository.Create<TBusinessObject>(entity);
        }

        public virtual TBusinessObject Update(TBusinessObject entity)
        {
            if (entity == null)
                throw new DomainException("يجب أن لايكون الكائن فارغاً");

            // the return value represent the persisted entity
            // if the creation done successfully.
            return Repository.Update<TBusinessObject>(entity);
        }

        /// <summary>
        /// Delete array of business entity from the repository.
        /// </summary>
        /// <param name="groups">array of business entities to be deleted.</param>
        /// <returns>True, if delete operation done successfully. False, otherwise.</returns>
        public virtual bool Delete(IEnumerable<TBusinessObject> entities)
        {
            if (entities == null || entities.Count() == 0)
                throw new DomainException("يجب تحديد الكائن/الكائنات التي تريد حذفها!");

            return Repository.Delete<TBusinessObject>(entities);
        }

        /// <summary>
        /// Delete group object from repository.
        /// </summary>
        /// <param name="group"></param>
        /// <returns>True, if delete operation done successfully. False, otherwise.</returns>
        public virtual bool Delete(TBusinessObject entity)
        {
            if (entity == null)
                throw new DomainException("يجب تحديد الكائن/الكائنات التي تريد حذفها!");

            return Repository.Delete<TBusinessObject>(entity);
        }

        /// <summary>
        /// Returns total entity count.
        /// </summary>
        /// <returns></returns>
        public virtual int GetTotalCount()
        {
            return QueryRepository.GetCount<TBusinessObject>();
        }

        /// <summary>
        /// Returns pages count = TotalCount / PageSize.
        /// </summary>
        /// <returns></returns>
        public virtual int GetPageCount()
        {
            return GetTotalCount() / PageSize;
        }

        /// <summary>
        /// Retrieves page of entities.
        /// </summary>
        /// <param name="pageIndex">Index of entities's page that will be retrieved.</param>
        /// <returns></returns>
        public virtual List<TBusinessObject> GetPage(int pageIndex) { throw new NotImplementedException(); }

        /// <summary>
        /// Search for a page of entities.
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="searchText"></param>
        /// <returns></returns>
        public virtual List<TBusinessObject> SearchPage(SearchSpecification searchSpecs)
        {
            throw new NotImplementedException();
        }
    }
}
